package com.common.base.dao.impl;

import java.io.Serializable;
import java.sql.SQLException;
import java.util.*;

import org.springframework.orm.hibernate3.HibernateCallback;
import org.springframework.orm.hibernate3.HibernateTemplate;
import org.springframework.orm.hibernate3.support.HibernateDaoSupport;
import org.hibernate.*;
import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;

import com.common.base.dao.BaseDao;
import com.common.base.model.PaginationSupport;

public class BaseDaoImpl extends HibernateDaoSupport implements BaseDao{
	
	
	private static final Log log = LogFactory.getLog(BaseDao.class);
	

	public void save(Object entity){
		try{	 
			getHibernateTemplate().save(entity);
		} catch (RuntimeException e) {
			log.error("exec save: " + entity.getClass().getName() + " failed!",e);
			throw e;
		}		
	}

	public void saveOrUpdate(Object entity){
		try{
			getHibernateTemplate().saveOrUpdate(entity);
		} catch (RuntimeException e) {
			log.error("exec saveOrUpdate: " + entity.getClass().getName() + " failed!",e);
			throw e;
		}		
	}
	
	public void saveOrUpdate(List list){
		try{
			getHibernateTemplate().saveOrUpdateAll(list);
		} catch (RuntimeException e) {
			log.error("exec saveOrUpdate: " + list.getClass().getName() + " failed!",e);
			throw e;
		}		
	}
	
	public void merge(Object obj){
		if(obj==null)
			return;
		try{
			getHibernateTemplate().merge(obj);
		} catch (RuntimeException e) {
			log.error("exec merge: " + obj.getClass().getName() + " failed!",e);
			throw e;
		}		
	}
	
	public void delete(Object obj){
		if(obj==null)
			return;
		try{
			getHibernateTemplate().delete(obj);
		} catch(RuntimeException e){
			log.error("exec delete: " + obj.getClass().getName() + " Failed!",e);
			throw e;
		}
	}
	
	public void deleteAll(List list){
		if(list==null)
			return;
		try{
			getHibernateTemplate().deleteAll(list);
		} catch (RuntimeException e){
			log.error("exec delete: " + list.getClass().getName() + " failed!",e);
			throw e;
		}
	}
	
	public Object findById(String entityName,Serializable id){
		if(id==null)
			return null;
		try{
			return (Object)getHibernateTemplate().get(entityName,id);
		}catch (RuntimeException e){
			log.error("exec findById : "+ entityName +"/"+ id + " failed!",e);
			throw e;
		}
	}
	
	public  List findByHql(String hql){
		return getHibernateTemplate().find(hql);
	}
	
	public List findAll(String entityName){
		try{
			return getHibernateTemplate().find("from " + entityName);
		}catch (RuntimeException e){
			log.error("exec findAll : "+ entityName+ " failed!",e);
			throw e;
		}
	}
	
	
	
	
	
	
	
	
	
	
	
	
	
	
	
    

    
    
    
    public List findByNamedQuery(final String namedQuery) {
        return getHibernateTemplate().findByNamedQuery(namedQuery);
    }
    
    public List findByNamedQuery(final String query, final Object parameter) {
        return getHibernateTemplate().findByNamedQuery(query, parameter);
    }
    
    public List findByNamedQuery(final String query, final Object[] parameters)
    {
        return getHibernateTemplate().findByNamedQuery(query, parameters);
    }
    
    public PaginationSupport executeHQLPage(final int startIndex,final int pageSize,final String namedQuery,final Object[] parameters) {
        return (PaginationSupport) getHibernateTemplate().execute(
                new HibernateCallback() {
                    public PaginationSupport doInHibernate(final Session session)
                            throws HibernateException, SQLException {
                        final Query query = session.createQuery(namedQuery);
                        for(int i=0;parameters!=null&&i<parameters.length;i++){
                            query.setParameter(i, parameters[i]);
                        }
                        int totalCount=query.list().size();//(Integer)query.uniqueResult();
                        int tmp_startIndex = startIndex;
                        if(startIndex>=totalCount){
                            tmp_startIndex=(totalCount/pageSize-1)*pageSize;
                        }
                        query.setFirstResult(tmp_startIndex);
                        query.setMaxResults(pageSize); 
                        PaginationSupport ps = new PaginationSupport(query.list(), totalCount,
                                pageSize, tmp_startIndex);
                        return ps;
                    }
                }); 
    } 

    public Integer executeHQL(final String namedQuery,final Object[] parameters) {
        return (Integer) getHibernateTemplate().execute(
                new HibernateCallback() {
                    public Object doInHibernate(final Session session)
                            throws HibernateException, SQLException {
                        final Query query = session.getNamedQuery(namedQuery);
                        for(int i=0;parameters!=null&&i<parameters.length;i++){
                            query.setParameter(i, parameters[i]);
                        } 
                        Object obj = query.uniqueResult();
                        int result = 0;
                        if(obj!=null){
                        	result = 1;
                        }
                        return result;
                    }
                }); 
    }
    
    public List executeHQLList(final String namedQuery,final Object[] parameters) {
        return (List) getHibernateTemplate().execute(
                new HibernateCallback() {
                    public Object doInHibernate(final Session session)
                            throws HibernateException, SQLException {
                        final Query query = session.getNamedQuery(namedQuery);
                        for(int i=0;parameters!=null&&i<parameters.length;i++){
                            query.setParameter(i, parameters[i]);
                        } 
                        List obj = query.list();
                        
                        return obj;
                    }
                }); 
    }
    
    
    public PaginationSupport findAll(String entityName,Integer firstRow,Integer maxRow) {
		return findByWhereOrderBy(entityName,null,null,null,firstRow,maxRow);
	}
	
	public List findAllOrderBy(String entityName,String orderField,String order){
		return findByWhereOrderBy(entityName,null,orderField,order);
	}
	
	public PaginationSupport findAllOrderBy(String entityName,String orderField,String order,Integer firstRow,Integer maxRow){
		return findByWhereOrderBy(entityName,null,orderField,order,firstRow,maxRow);
	}
	
	public List findByWhere(String entityName,String where){
		return findByWhereOrderBy(entityName,where,null,null);
	}
	
	public PaginationSupport findByWhere(String entityName,String where,Integer firstRow,Integer maxRow){
		return findByWhereOrderBy(entityName,where,null,null,firstRow,maxRow);
	}
	
	public List findByWhereOrderBy(String entityName,String where,String orderField, String order){
		String hql = "from " + entityName;
		if(where != null)
			hql += " where " + where;
		if(orderField != null && order != null)
			hql += " order by " + orderField + " " + order;	
		try{
			final String fhql = hql;
			return getHibernateTemplate().executeFind(
					new HibernateCallback(){
						public Object doInHibernate(Session session)
								throws HibernateException, SQLException {
							// TODO Auto-generated method stub
							Query query = (Query)session.createQuery(fhql);
							return query.list();
						}
					}
			);
		}catch(RuntimeException e){
			log.error("exec find : " + hql + " failed!",e);
			throw e;
		}
	}
	
	
	public PaginationSupport findByWhereOrderBy(String entityName,String where,String orderField, String order,final Integer startIndex,final Integer pageSize){
		String hql = "from " + entityName;
		if(where != null)
			hql += " where " + where;
		if(orderField != null && order != null)
			hql += " order by " + orderField + " " + order;	
		try{
			final String fhql = hql;
//			return (PaginationSupport) getHibernateTemplate().executeFind(
//					new HibernateCallback(){
//						public Object doInHibernate(Session session)
//								throws HibernateException, SQLException {
//							
//						}
//					}
//			);
			
			Query query = (Query)getBaseSession().createQuery(fhql);
			int totalCount=query.list().size();
            int tmp_startIndex = startIndex;
            if(startIndex>=totalCount){
                tmp_startIndex=(totalCount/pageSize-1)*pageSize;
            }
			if(startIndex != null && pageSize != null){
				query.setFirstResult(startIndex.intValue());
				query.setMaxResults(pageSize.intValue());
			}	
			PaginationSupport ps = new PaginationSupport(query.list(), totalCount,
                    pageSize, tmp_startIndex);
            return ps;
		}catch(RuntimeException e){
			log.error("exec find : " + hql + " failed!",e);
			throw e;
		}
	}
    
    
    

	public HibernateTemplate getBaseHibernateTemplate(){
		return this.getHibernateTemplate();
	}
	
	public Session getBaseSession(){
		return this.getSession();
	}
	
	public void closeSession(Session s){
		this.releaseSession(s) ;
	}

}
